package com.qys.livesMall.shop.controller.app;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qys.livesMall.cache.words.annotation.CheckWord;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.product.entity.*;
import com.qys.livesMall.product.service.H2ProductCategoryService;
import com.qys.livesMall.product.service.H2ProductGoodsinfoService;
import com.qys.livesMall.product.service.H2ProductSkuAttributeService;
import com.qys.livesMall.product.service.ProductSkuAttributeOptionsService;
import com.qys.livesMall.shop.dao.H2ShopBaseDao;
import com.qys.livesMall.shop.enums.ShopMessageEnum;
import com.qys.livesMall.shop.mapper.ShopGoodsSkuMapper;
import com.qys.livesMall.shop.modal.dto.QueryProductsDTO;
import com.qys.livesMall.shop.modal.dto.ShopGoodsInfoDto;
import com.qys.livesMall.shop.modal.dto.ShopGoodsStockDto;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.modal.query.QueryGoods;
import com.qys.livesMall.shop.modal.query.RequestData;
import com.qys.livesMall.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺商品
 * </p>
 *
 * @author gmx
 * @since 2023-06-07
 */
@RestController
@RequestMapping("/app/shopGoodsInfo")
@Tag(name = "App-商铺商品信息", description = "App-商品信息")
public class AppShopGoodsInfoController {
    @Resource
    ShopGoodsInfoService goodsInfoService;
    @Resource
    ShopGoodsSkuService goodsSkuService;
    @Resource
    H2ProductSkuAttributeService attributeService;
    @Resource
    ProductSkuAttributeOptionsService optionsService;

    @Resource
    H2ProductGoodsinfoService productGoodsinfoService;

    @Resource
    private ShopRecordService shopRecordService;

    @Resource
    private H2ShopBaseDao h2ShopBaseDao;
    @Resource
    ShopGoodsSkuStocksService stocksService;
    @Resource
    H2ProductCategoryService categoryService;
    @Resource
    private ShopSellTaskService shopSellTaskService;
    @Resource
    private SeckillActivityService seckillActivityService;


    @Autowired
    private ShopGoodsSkuMapper shopGoodsSkuMapper;

    @PostMapping("/page")
    @Operation(summary = "商品信息分页-商铺仓库")
    @CheckWord
    public R<Page<ShopGoodsStockDto>> page(@RequestBody QueryGoods data) {
        Page<ShopGoodsStockDto> page = new Page<>(data.getCurrent(),data.getSize());
        //当前店铺sku库存大于0的
        page = shopGoodsSkuMapper.stockZeroShopGoodsPage(page,data.getShopId() == null ? h2ShopBaseDao.queryShopBaseIdByUserId(SecurityUtils.getUserId()): data.getShopId(),data.isStatus());
        return R.ok(page);
    }

    /**
     * 商品删除
     * @param goodsId
     * @return
     */
    @PostMapping("/deleteShopGoodsInfo/{goodsId}")
    @Operation(summary = "商品删除")
    public R<?> deleteShopGoodsInfo(@PathVariable Long goodsId){
        goodsInfoService.removeById(goodsId);
        return R.ok();
    }


    @PostMapping("/userpage")
    @Operation(summary = "商品信息分页-商铺商品列表")
    @CheckWord
    public R<Page<ShopGoodsInfo>> userpage(@RequestBody RequestData<QueryGoods> data){
        Page<QueryGoods> oldPage = data.getPage();
        QueryGoods r = data.getData();
        LambdaQueryWrapper<ShopGoodsInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopGoodsInfo::isStatus, true);
        queryWrapper.eq(ShopGoodsInfo::getIsDelete,"1");
        if (r.getShopId() == null) {
            Long shopBaseId = h2ShopBaseDao.queryShopBaseIdByUserId(SecurityUtils.getUserId());
            queryWrapper.eq(ShopGoodsInfo::getShopId, shopBaseId);
        } else {
            queryWrapper.eq(ShopGoodsInfo::getShopId, r.getShopId());
        }
        Page<ShopGoodsInfo> page = new Page<>();
        page.setSize(oldPage.getSize());
        page.setCurrent(oldPage.getCurrent());
        Page<ShopGoodsInfo> result = goodsInfoService.page(page, queryWrapper);
        for (ShopGoodsInfo record : result.getRecords()) {
            List<ShopGoodsSku> shopGoodsSkus = shopGoodsSkuMapper.selectList(Wrappers.<ShopGoodsSku>lambdaQuery().eq(ShopGoodsSku::getShopGoodsId, record.getId()));
            if(CollectionUtils.isEmpty(shopGoodsSkus)){
                record.setTotalInventory(0);
            } else {
                List<Long> ids = shopGoodsSkus.stream().map(ShopGoodsSku::getId).collect(Collectors.toList());
                ShopGoodsSkuStocks one = stocksService.getOne(Wrappers.<ShopGoodsSkuStocks>query().select("sum(num) as num").in("sku_id", ids).eq("state", 0));
                record.setTotalInventory(one.getNum());
            }
        }
        return R.ok(result);
    }
    @PostMapping("/useraLLpage")
    @Operation(summary = "商品信息分页首页")
    public R<Page<ShopGoodsInfo>> userAllpage(@RequestBody QueryGoods page){
        LambdaQueryWrapper<ShopGoodsInfo> goodsInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        goodsInfoLambdaQueryWrapper.eq(ShopGoodsInfo::isStatus,true);
        if(ObjectUtils.isNotEmpty(page.getShopId())){
            goodsInfoLambdaQueryWrapper.eq(ShopGoodsInfo::getShopId,page.getShopId());
        }else {
            List<H2ShopBase> shopBases=h2ShopBaseDao.getAllShop();
            if (CollectionUtils.isNotEmpty(shopBases)){
                List<Long> shopIds=shopBases.stream().map(H2ShopBase::getId).collect(Collectors.toList());
                goodsInfoLambdaQueryWrapper.in(ShopGoodsInfo::getShopId,shopIds);
            }
        }
        if (ObjectUtils.isNotEmpty(page.getName())){
            goodsInfoLambdaQueryWrapper.like(ShopGoodsInfo::getGoodsName,page.getName());
        }
        goodsInfoLambdaQueryWrapper.eq(ShopGoodsInfo::getIsDelete,"1");
        if (ObjectUtils.isNotEmpty(page.getCateId())){
            goodsInfoLambdaQueryWrapper.and(wrapper->wrapper.eq(ShopGoodsInfo::getCategoryTwoId,page.getCateId())
                    .or().eq(ShopGoodsInfo::getCategoryOneId,page.getCateId()));
        }
        if(page.getSortType() != null){
            switch (page.getSortType()) {
                case 2 -> goodsInfoLambdaQueryWrapper.orderByDesc(ShopGoodsInfo::getSalesVolume);
                case 3 -> goodsInfoLambdaQueryWrapper.orderByDesc(ShopGoodsInfo::getCreateTime);
                case 4 -> goodsInfoLambdaQueryWrapper.orderByDesc(ShopGoodsInfo::getPrice);
                case 5 -> goodsInfoLambdaQueryWrapper.orderByAsc(ShopGoodsInfo::getSalesVolume);
                case 6 -> goodsInfoLambdaQueryWrapper.orderByAsc(ShopGoodsInfo::getCreateTime);
                case 7 -> goodsInfoLambdaQueryWrapper.orderByAsc(ShopGoodsInfo::getPrice);
                //随机显示。不同用户看到的数据不同，但每个用户多次看到的数据相同
                default -> goodsInfoLambdaQueryWrapper.last(String.format("order by rand(%s)", SecurityUtils.getUserId()));
            }
        }
        Page<ShopGoodsInfo> pages = Page.of(page.getCurrent(),page.getSize());
        Page<ShopGoodsInfo> result = goodsInfoService.page(pages,goodsInfoLambdaQueryWrapper);
        return R.ok(result);
    }

    @GetMapping("/productRecommended")
    @Operation(summary = "商品推荐")
    public R<List<ShopGoodsInfo>> productRecommended(){
        return R.ok(goodsInfoService.productRecommended());
    }

    /**
     * 商品详情
     * @param productId
     * @return
     */
    @GetMapping("/product/{productId}")
    @Operation(summary = "商品详情")
    public R<ShopProduct> shopProduct(@PathVariable Long productId){
        ShopGoodsInfo goodsInfo = goodsInfoService.getById(productId);
        if(ObjectUtils.isEmpty(goodsInfo)){
            return R.fail(MessageUtils.message("not.find.goods"));
        }
        if(!goodsInfo.isStatus()){
            H2ShopBase shop=h2ShopBaseDao.getById(goodsInfo.getShopId());
            if (!Objects.equals(shop.getUserId(),SecurityUtils.getUserId())) {
                ShopProduct shopProduct = new ShopProduct();
                shopProduct.setGoodsInfo(goodsInfo);
                return R.ok(shopProduct);
            }
        }
        LambdaQueryWrapper<ShopGoodsSku> skuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        skuLambdaQueryWrapper.eq(ShopGoodsSku::getShopGoodsId,goodsInfo.getId());
        List<ShopGoodsSku> skuList = goodsSkuService.list(skuLambdaQueryWrapper);
        for (ShopGoodsSku shopGoodsSku : skuList) {
            Long skuId = shopGoodsSku.getId();
            LambdaQueryWrapper<ShopGoodsSkuStocks> stocksWrapper = new LambdaQueryWrapper<>();
            stocksWrapper.eq(ShopGoodsSkuStocks::getSkuId,skuId);
            stocksWrapper.eq(ShopGoodsSkuStocks::getState,false);
            stocksWrapper.ne(ShopGoodsSkuStocks::getNum, 0);
            stocksWrapper.orderByAsc(ShopGoodsSkuStocks::getCreateTime);
            List<ShopGoodsSkuStocks> stocks = stocksService.list(stocksWrapper);
            if (ObjectUtils.isNotEmpty(stocks)) {
                int totalNum = stocks.stream().mapToInt(ShopGoodsSkuStocks::getNum).sum();
                ShopGoodsSkuStocks minStocks = stocks.stream().min(Comparator.comparing(ShopGoodsSkuStocks::getCreateTime)).orElse(null);
                Integer num = minStocks.getNum();
                BigDecimal price = minStocks.getPrice();
                shopGoodsSku.setTotalNum(totalNum);
                shopGoodsSku.setAvailableNum(num);
                shopGoodsSku.setPrice(price);
                shopGoodsSku.setOriginalPrice(price);
            }else {

                shopGoodsSku.setTotalNum(0);
                shopGoodsSku.setAvailableNum(0);
            }
        }
        LambdaQueryWrapper<H2ProductSkuAttribute> attributeLambdaQueryWrapper= new LambdaQueryWrapper<>();
        attributeLambdaQueryWrapper.eq(H2ProductSkuAttribute::getSpuId,goodsInfo.getGoodsId());
        List<H2ProductSkuAttribute> attributeList = attributeService.list(attributeLambdaQueryWrapper);
        for (H2ProductSkuAttribute attribute : attributeList) {
            LambdaQueryWrapper<ProductSkuAttributeOptions> optionQueryWrapper = new LambdaQueryWrapper<>();
            optionQueryWrapper.eq(ProductSkuAttributeOptions::getAttrId, attribute.getId());
            List<ProductSkuAttributeOptions> optionList = optionsService.list(optionQueryWrapper);
            attribute.setOptions(optionList);
        }
        int i = shopRecordService.isInterestShopGoods(goodsInfo.getId());
        ShopProduct shopProduct = new ShopProduct();
        shopProduct.setGoodsInfo(goodsInfo);
        shopProduct.setGoodsSkus(skuList);
        shopProduct.setSkuAttributes(attributeList);
        shopProduct.setCollectStatus(i);
        return R.ok(shopProduct);
    }
    @Operation(summary = "商品上下架")
    @GetMapping("/{goodsId}")
    public R Controls(@PathVariable Long goodsId){
        try {
            ShopGoodsInfo goodsInfo = goodsInfoService.getById(goodsId);
            List<ShopSellTask> shopSellTasks=shopSellTaskService.getByGoodsId(goodsId,goodsInfo.getShopId());
            if (CollectionUtils.isNotEmpty(shopSellTasks)){
                R.fail(MessageUtils.message("shop.lives.goods.afoot"));
            }
            List<SeckillActivity> seckillActivities=seckillActivityService.getByGoodsId(goodsId,goodsInfo.getShopId());
            if (CollectionUtils.isNotEmpty(seckillActivities)){
                R.fail(MessageUtils.message("seckill.activity.goods.afoot"));
            }
            goodsInfo.setStatus(!goodsInfo.isStatus());
            goodsInfo.setUpShelfDate(LocalDateTime.now());
            goodsInfoService.upDown(goodsId,!goodsInfo.isStatus());

            return R.ok();
        }catch (QysException e){
            return R.fail(e.getMessage());
        }
    }

    @GetMapping("/cate/{shopId}")
    public R<List<H2ProductCategory>> cate(@PathVariable Long shopId){
        LambdaQueryWrapper<ShopGoodsInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopGoodsInfo::isStatus,true);
        queryWrapper.eq(ShopGoodsInfo::getIsDelete,"1");
        if (shopId==0){
            return R.ok(categoryService.list());
        }
        queryWrapper.eq(ShopGoodsInfo::getShopId,shopId);
        List<ShopGoodsInfo> goodList = goodsInfoService.list(queryWrapper);
        if (ObjectUtils.isEmpty(goodList))return R.ok(new ArrayList<H2ProductCategory>());
        Set<Long> ids = goodList.stream().map(ShopGoodsInfo::getGoodsId).collect(Collectors.toSet());
        LambdaQueryWrapper<H2ProductGoodsinfo> productGoodsinfoWrapper = new LambdaQueryWrapper<>();
        productGoodsinfoWrapper.in(H2ProductGoodsinfo::getId,ids);
        productGoodsinfoWrapper.groupBy(H2ProductGoodsinfo::getCategoryTwoId);
        List<H2ProductGoodsinfo> goodsList = productGoodsinfoService.list(productGoodsinfoWrapper);
        Set<Long> cateIds = goodsList.stream().map(H2ProductGoodsinfo::getCategoryOneId).collect(Collectors.toSet());
        Set<Long> cateIdTwos = goodsList.stream().map(H2ProductGoodsinfo::getCategoryTwoId).collect(Collectors.toSet());
        Set<Long> mergedSet = new HashSet<>();
        mergedSet.addAll(cateIds);
        mergedSet.addAll(cateIdTwos);
        LambdaQueryWrapper<H2ProductCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        categoryLambdaQueryWrapper.in(H2ProductCategory::getId,mergedSet);
        return R.ok(categoryService.list(categoryLambdaQueryWrapper));
    }


    @GetMapping("/cateTwo/{shopId}")
    public R<List<H2ProductCategory>> cateTwo(@PathVariable Long shopId){
        LambdaQueryWrapper<ShopGoodsInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopGoodsInfo::isStatus,true);
        queryWrapper.eq(ShopGoodsInfo::getIsDelete,"1");
        if (shopId==0){
            return R.ok(categoryService.list());
        }
        queryWrapper.eq(ShopGoodsInfo::getShopId,shopId);
        List<ShopGoodsInfo> goodList = goodsInfoService.list(queryWrapper);
        if (ObjectUtils.isEmpty(goodList))return R.ok(new ArrayList<H2ProductCategory>());
        Set<Long> ids = goodList.stream().map(ShopGoodsInfo::getGoodsId).collect(Collectors.toSet());
        LambdaQueryWrapper<H2ProductGoodsinfo> productGoodsinfoWrapper = new LambdaQueryWrapper<>();
        productGoodsinfoWrapper.in(H2ProductGoodsinfo::getId,ids);
        productGoodsinfoWrapper.groupBy(H2ProductGoodsinfo::getCategoryTwoId);
        List<H2ProductGoodsinfo> goodsList = productGoodsinfoService.list(productGoodsinfoWrapper);
        Set<Long> cateIds = goodsList.stream().map(H2ProductGoodsinfo::getCategoryOneId).collect(Collectors.toSet());
        Set<Long> cateIdTwos = goodsList.stream().map(H2ProductGoodsinfo::getCategoryTwoId).collect(Collectors.toSet());
        Set<Long> mergedSet = new HashSet<>();
        mergedSet.addAll(cateIds);
        mergedSet.addAll(cateIdTwos);
        LambdaQueryWrapper<H2ProductCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        categoryLambdaQueryWrapper.in(H2ProductCategory::getId,mergedSet);
        List<H2ProductCategory> total=categoryService.list(categoryLambdaQueryWrapper);
        List<H2ProductCategory> ones=total.stream().filter(o->Objects.equals(o.getLevel(),"1")).collect(Collectors.toList());
        ones.stream().forEach(one->{
            one.setTwos(total.stream().filter(o->Objects.equals(one.getId(),o.getParentId())).collect(Collectors.toList()));
        });
        return R.ok(ones);
    }

    @Operation(summary = "商品分类")
    @GetMapping("/category/{parentId}")
    public  R<List<H2ProductCategory>> categorylist(@PathVariable Long parentId){
        List<H2ProductCategory> categories = categoryService.queryByParentId(parentId);
        return R.ok(categories);
    }
    @Operation(summary = "所有商品分类")
    @GetMapping("/categoryAll")
    public R<List<H2ProductCategoryDTO>> categoryAll() {
        LambdaQueryWrapper<H2ProductCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        categoryLambdaQueryWrapper.eq(H2ProductCategory::getEnable,1);
        categoryLambdaQueryWrapper.eq(H2ProductCategory::getIsDelete,0);
        List<H2ProductCategory> categories = categoryService.list(categoryLambdaQueryWrapper);
        List<H2ProductCategoryDTO> categoryDTOList = new ArrayList<>();

        List<H2ProductCategory> pList = categories.stream()
                .filter(category -> category.getParentId().equals(0L)).toList();

        for (H2ProductCategory category : pList) {
            H2ProductCategoryDTO categoryDTO = new H2ProductCategoryDTO();
            BeanUtil.copyProperties(category, categoryDTO);
            List<H2ProductCategory> child = categories.stream()
                    .filter(categoryTwo ->categoryTwo.getParentId().equals(categoryDTO.getId()))
                    .collect(Collectors.toList());


            categoryDTO.setChild(child);
            categoryDTOList.add(categoryDTO);
        }

        return R.ok(categoryDTOList);
    }

    @PostMapping("/queryProductsBasedOnUserPreferences")
    @Operation(summary = "根据用户偏好查询商品")
    public R<List<ShopGoodsInfo>> queryProductsBasedOnUserPreferences(@RequestBody QueryProductsDTO dto) {
        return R.ok(goodsInfoService.queryProductsBasedOnUserPreferences(dto));
    }

}


